/**
 * 
 */
package com.csc.bankingsystem.core.service.impl;

import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.csc.bankingsystem.core.dao.TransferRecordDAO;
import com.csc.bankingsystem.core.dto.BSPaging;
import com.csc.bankingsystem.core.entity.AccountInfo;
import com.csc.bankingsystem.core.entity.HistoryRecord;
import com.csc.bankingsystem.core.entity.TransferRecord;
import com.csc.bankingsystem.core.entity.UserInfo;
import com.csc.bankingsystem.core.enumeration.HistoryRecordActionEnum;
import com.csc.bankingsystem.core.enumeration.TransferRecordStatusEnum;
import com.csc.bankingsystem.core.enumeration.TransferRecordUnitEnum;
import com.csc.bankingsystem.core.exception.NotEnoughMoneyException;
import com.csc.bankingsystem.core.service.AccountInfoService;
import com.csc.bankingsystem.core.service.HistoryRecordService;
import com.csc.bankingsystem.core.service.TransferRecordService;
import com.csc.bankingsystem.core.util.ConstantManager;

/**
 * Implement all service operation of TransferRecordService
 * 
 * @author angelkid
 *
 */
@Service("transferRecordService")
@Transactional
public class TransferRecordServiceImpl implements TransferRecordService {
	@Autowired
	TransferRecordDAO transferRecordDAO;

	@Autowired
	HistoryRecordService historyRecordService;

	@Autowired
	AccountInfoService accountInfoService;

	public TransferRecord find(long id) {
		return transferRecordDAO.find(id);
	}

	public List<TransferRecord> findAll() {
		return transferRecordDAO.findAll();
	}

	public Long countAll() {
		return transferRecordDAO.countAll();
	}

	public Long save(TransferRecord transferRecord) {
		return transferRecordDAO.save(transferRecord);
	}

	public void update(TransferRecord transferRecord) {
		transferRecordDAO.update(transferRecord);
	}

	public void delete(TransferRecord transferRecord) {
		transferRecordDAO.delete(transferRecord);
	}

	public List<TransferRecord> findByUserInfo(BSPaging paging, UserInfo userInfo,Date toDate) {
		return transferRecordDAO.findByUserInfo(paging, userInfo, toDate);
	}

	public void createTransferRecord(UserInfo curUserInfo, AccountInfo source,
			AccountInfo destination, Long amount, String message) throws NotEnoughMoneyException {

		Date now = new Date();

		Long sourceFinalAmount = source.getAmount() - amount;

		if (sourceFinalAmount < ConstantManager.MINIMUM_ACCOUNT_AMOUNT) {
			throw new NotEnoughMoneyException(
					ConstantManager.TRANSFER_NOT_ENOUGH_MONEY,
					"Not enough money in source account after transfer");
		}
		source.setAmount(source.getAmount() - amount);
		destination.setAmount(destination.getAmount() + amount);
		source.setUpdateUser(curUserInfo.getLoginId());
		source.setUpdateDate(now);
		destination.setUpdateDate(now);
		destination.setUpdateUser(curUserInfo.getLoginId());
		
		TransferRecord transferRecord = new TransferRecord();
		HistoryRecord historyRecord = new HistoryRecord();

		historyRecord.setAction(HistoryRecordActionEnum.TRANSFER);
		historyRecord.setCreateDate(now);
		historyRecord.setCreateUser(curUserInfo.getLoginId());
		historyRecord.setUserInfo(curUserInfo);
		historyRecord.setStartTime(now);
		long historyRecordId = historyRecordService.save(historyRecord);
		historyRecord = historyRecordService.find(historyRecordId);

		transferRecord.setSource(source);
		transferRecord.setDestination(destination);
		transferRecord.setAmount(amount);
		transferRecord.setMessage(message);
		transferRecord.setStatus(TransferRecordStatusEnum.SUCCESS);
		transferRecord.setUnit(TransferRecordUnitEnum.VND);
		transferRecord.setCreateDate(now);
		transferRecord.setCreateUser(curUserInfo.getLoginId());
		transferRecord.setTransDate(now);
		transferRecord.setRemainAmount(source.getAmount());
		transferRecord.setHistoryRecord(historyRecord);
		save(transferRecord);
		
		accountInfoService.update(source);
		accountInfoService.update(destination);

	}
}
